import { getBusinessObject, is } from "bpmn-js/lib/util/ModelUtil";
import editor from '@/store/editor'
import modeler from '@/store/modeler'
import {
  createModdleElement,
  getExtensionElementsList
} from '@/utils/BpmnExtensionElementsUtil'
/////// 功能函数
export function getFormValue(element) {
  const businessObject = getRelevantBusinessObject(element);

  if (!businessObject) return {};

  return getElementValue(businessObject) || {};
}

//设置会签类型
export function updateLoopType(element, value) {
  const modeling = modeler().getModeling
  const businessObject = getRelevantBusinessObject(element);
  // 判断 multiInstanceLoopCharacteristics
  let loopCharacteristics = getMultiInstanceLoop(businessObject);
  if (value) {
    if (!loopCharacteristics) {
      loopCharacteristics = createModdleElement(
        "bpmn:MultiInstanceLoopCharacteristics",
        {
          isSequential: value === "seq"
        },
        businessObject
      );
    } else {
      modeling?.updateModdleProperties(element, loopCharacteristics, {
        isSequential: value === "seq"
      });
    }
  } else {
    loopCharacteristics = undefined;
  }
  modeling?.updateModdleProperties(element, businessObject, {
    loopCharacteristics
  });
}

//更新实例数量
export function updateLoopCardinality(element, value) {
  const modeling = modeler().getModeling
  const businessObject = getRelevantBusinessObject(element);

  // 判断 multiInstanceLoopCharacteristics
  let multiInstanceLoop = getMultiInstanceLoop(businessObject);

  if (!multiInstanceLoop) {
    multiInstanceLoop = createModdleElement(
      "bpmn:MultiInstanceLoopCharacteristics",
      {},
      businessObject
    );
    modeling?.updateModdleProperties(element, businessObject, {
      multiInstanceLoop
    });
  }
  let loopCardinality;
  if (value) {
    loopCardinality = createModdleElement(
      `bpmn:FormalExpression`,
      { body: value },
      multiInstanceLoop
    );
  } else {
    const loopCardinality = multiInstanceLoop.get("loopCardinality");
    if (loopCardinality) {
      delete multiInstanceLoop.loopCardinality;
    }
  }
  modeling?.updateModdleProperties(element, multiInstanceLoop, {
    loopCardinality: loopCardinality
  });
}

//更新完成条件
export function updateCompletionCondition(element, value) {
  const modeling = modeler().getModeling
  const businessObject = getRelevantBusinessObject(element);

  // 判断 multiInstanceLoopCharacteristics
  let multiInstanceLoop = getMultiInstanceLoop(businessObject);

  if (!multiInstanceLoop) {
    multiInstanceLoop = createModdleElement(
      "bpmn:MultiInstanceLoopCharacteristics",
      {},
      businessObject
    );
    modeling?.updateModdleProperties(element, businessObject, {
      multiInstanceLoop
    });
  }
  let newCompletionCondition;
  if (value) {
    newCompletionCondition = createModdleElement(
      `bpmn:FormalExpression`,
      { body: value },
      multiInstanceLoop
    );
  } else {
    const completionCondition = multiInstanceLoop.get("completionCondition");
    if (completionCondition) {
      delete multiInstanceLoop.completionCondition;
    }
  }
  modeling?.updateModdleProperties(element, multiInstanceLoop, {
    completionCondition: newCompletionCondition
  });
}

// 更新重试周期
export function updateTimeCycle(element, value) {
  const modeling = modeler().getModeling
  const businessObject = getRelevantBusinessObject(element);
  const prefix = editor().getProcessEngine
  // 判断 multiInstanceLoopCharacteristics
  let multiInstanceLoop = getMultiInstanceLoop(businessObject);

  if (!multiInstanceLoop) {
    multiInstanceLoop = createModdleElement(
      "bpmn:MultiInstanceLoopCharacteristics",
      {},
      businessObject
    );
    modeling?.updateModdleProperties(element, businessObject, {
      multiInstanceLoop
    });
  }
  let extensionElements = multiInstanceLoop.get("extensionElements");
  if (value) {
    // 更新重试周期
    if (!extensionElements) {
      extensionElements = createModdleElement(
        "bpmn:ExtensionElements",
        { values: [] },
        multiInstanceLoop
      );
      modeling?.updateModdleProperties(element, multiInstanceLoop, {
        extensionElements
      });
    }
    const timeCycle = createModdleElement(
      `${prefix}:FailedJobRetryTimeCycle`,
      { body: value },
      extensionElements
    );
    modeling?.updateModdleProperties(element, extensionElements, {
      values: [timeCycle]
    });
  } else {
    // 删除重试周期
    modeling?.updateModdleProperties(element, multiInstanceLoop, {
      extensionElements: undefined
    });
  }
}

//更新属性collection、elementVariable、acBefore、acAfter
export function updateLoopCharacteristics(element, attribute) {
  const modeling = modeler().getModeling;
  const businessObject = getRelevantBusinessObject(element);
  const prefix = editor().getProcessEngine
  // 判断 multiInstanceLoopCharacteristics
  let multiInstanceLoop = getMultiInstanceLoop(businessObject);

  if (!multiInstanceLoop) {
    multiInstanceLoop = createModdleElement(
      "bpmn:MultiInstanceLoopCharacteristics",
      {},
      businessObject
    );
    modeling?.updateModdleProperties(element, businessObject, {
      multiInstanceLoop
    });
  }
  const obj = {};
  // 拼接prefix
  Object.keys(attribute).forEach(key => {
    obj[`${prefix}:${key}`] = attribute[key];
  });
  modeling?.updateModdleProperties(element, multiInstanceLoop, {
    ...obj
  });
}

///// helpers
function getRelevantBusinessObject(element) {
  const businessObject = getBusinessObject(element);
  if (is(element, "bpmn:Participant")) {
    return businessObject.get("processRef");
  }
  return businessObject;
}

export function getElementValue(businessObject) {
  const prefix = editor().getProcessEngine
  const loopCharacteristics = getMultiInstanceLoop(businessObject);
  if (!loopCharacteristics) {
    return {};
  }
  const timeCycle = getTimeCycle(loopCharacteristics);
  return {
    type: loopCharacteristics.get(`isSequential`) ? "seq" : "parallel",
    loopCardinality: loopCharacteristics.get("loopCardinality")?.body,
    completionCondition: loopCharacteristics.get("completionCondition")?.body,
    collection: loopCharacteristics.get(`${prefix}:collection`),
    elementVariable: loopCharacteristics.get(`${prefix}:elementVariable`),
    acBefore: loopCharacteristics.get(`${prefix}:acBefore`),
    acAfter: loopCharacteristics.get(`${prefix}:acAfter`),
    exclusive: loopCharacteristics.get(`${prefix}:exclusive`),
    timeCycle: timeCycle?.body
  };
}

function getTimeCycle(bo) {
  const extensionElementsList = getExtensionElementsList(bo);
  const prefix = editor().getProcessEngine
  return extensionElementsList.filter(
    ex => ex.$type === `${prefix}:FailedJobRetryTimeCycle`
  )?.[0];
}

// 获取多实例对象节点
function getMultiInstanceLoop(bo) {
  const multiInstanceLoop = bo.get("loopCharacteristics");
  if (
    !multiInstanceLoop ||
    multiInstanceLoop.$type !== "bpmn:MultiInstanceLoopCharacteristics"
  ) {
    return "";
  }
  return multiInstanceLoop;
}

export function isMultiInstanceLoop(element) {
  return is(element, `bpmn:UserTask`);
}
